#include "common.h"

static void writeCrl(X509_CRL *crl);
static int initCrlFromFile(const char* filename, X509_CRL *crl);

int main(int argc, char* argv[])
{
    X509_EXTENSION *ext;
    int ext_index;
    X509_CRL *crl;

    if(0 != initCrlFromFile("/home/ts/document/zhb/ca/crl/crl.pem", crl))
    {
        printf("bin to big number fail!");
        return CF_ERR_CRYPTO_OPERATION;
    }

    //Serial Number: FF01FF01FF01FF01FFFFFFFFFFFFFFFFFF01
    uint8_t testSn[] = {0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01, 0xFF, 0x01,
                        0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
                        0xFF, 0x01};
    CfBlob serialNumber = {sizeof(testSn)/sizeof(testSn[0]), testSn};

    BIGNUM *bigNum = BN_bin2bn(serialNumber.data, serialNumber.size, NULL);
    if (bigNum == NULL) {
        printf("bin to big number fail!");
        return CF_INVALID_PARAMS;
    }
    ASN1_INTEGER *serial = BN_to_ASN1_INTEGER(bigNum, NULL);

    if (serial == NULL) {
        printf("Serial init fail!");
        BN_free(bigNum);
        return CF_ERR_CRYPTO_OPERATION;
    }

    X509_REVOKED *rev = NULL;
    int32_t opensslRes = X509_CRL_get0_by_serial(crl, &rev, serial);
    BN_free(bigNum);
    ASN1_INTEGER_free(serial);
    if (opensslRes != CF_OPENSSL_SUCCESS) {
        printf("Get revoked certificate fail, res : %d, at line %d.\n", opensslRes, __LINE__);
        return CF_ERR_CRYPTO_OPERATION;
    }

    // 创建 Extension 对象
    uint8_t data[] = "test";
    ASN1_BIT_STRING bitStr = { 4, V_ASN1_BIT_STRING, data, 0 };
    X509_EXTENSION *NetscapeCommentExt = X509V3_EXT_i2d(NID_netscape_comment, 1, (void *)(&bitStr));
    
    // 设置 Extension 的 critical 标志
    X509_EXTENSION_set_critical(NetscapeCommentExt, 1);

    int nRet = X509_REVOKED_add_ext(rev, NetscapeCommentExt, 1);
    if(0 == nRet){
        printf("X509_REVOKED_add_ext error, at line %d.\n", __LINE__);
        return CF_ERR_CRYPTO_OPERATION;
    }
    // // 创建 CRL Entry 对象
    // X509_CRL_ENTRY *crl_entry = X509_CRL_ENTRY_new();
    
    // // 设置证书序列号
    // ASN1_INTEGER *serial = ASN1_INTEGER_new();
    // ASN1_INTEGER_set(serial, 2023);  // 替换为实际的证书序列号
    // X509_CRL_ENTRY_set_serialNumber(crl_entry, serial);

    // // 设置撤销时间
    // ASN1_TIME *revocation_time = ASN1_TIME_new();
    // // 设置为当前时间，实际应用中可能需要替换为撤销时间
    // ASN1_TIME_set(revocation_time, time(NULL));
    // X509_CRL_ENTRY_set_revocationDate(crl_entry, revocation_time);

    // // 创建 Extension 对象
    // X509_EXTENSION *extension = X509_EXTENSION_create_by_NID(NULL, NID_invalid_extension, 1, ASN1_OCTET_STRING_new());
    // // 设置 Extension 的 critical 标志
    // X509_EXTENSION_set_critical(extension, 1);

    // // 将 Extension 添加到 CRL Entry
    // X509_CRL_ENTRY_add_ext(crl_entry, extension, -1);

    // 最后，释放资源
    // ASN1_INTEGER_free(serial);
    // ASN1_TIME_free(revocation_time);
    // X509_CRL_ENTRY_free(crl_entry);
    writeCrl(crl);


    // 重新生成CRL
    FILE *crlNewfile = fopen("new_crl.pem", "w");
    if (!crlNewfile) {
        printf("can not create CRL new file\n");
        return 1;
    }

    PEM_write_X509_CRL(crlNewfile, crl);
    fclose(crlNewfile);

    return 0;
}

static void writeCrl(X509_CRL *crl)
{
    BIO *bp;
    int len = 0;
    FILE *fp;
    FILE *fp1807 = fopen("new_crl1808.pem", "w");
    if (!fp1807) {
        printf("can not create CRL new file\n");
        return;
    }

    unsigned char* buf, *p;

    // 写入文件
    bp = BIO_new(BIO_s_file());
    BIO_set_fp(bp, stdout, BIO_NOCLOSE);
    X509_CRL_print(bp, crl);
    len = i2d_X509_CRL(crl, NULL);
    buf = malloc(len+10);
    p = buf;
    len = i2d_X509_CRL(crl,&p);
    fp = fopen("crl.crl","w");
    fwrite(buf,1,len,fp);
    fclose(fp);

    X509_CRL_print_fp(fp1807, crl);
    fclose(fp1807);
}

static int initCrlFromFile(const char* filename, X509_CRL *crl)
{
    // 打开CRL文件
    // crl_file = fopen("/home/ts/document/zhb/ca/crl/crl.pem", "r");
    FILE *crl_file = fopen(filename, "r");
    if (!crl_file) {
        printf("无法打开CRL文件\n");
        return 1;
    }

    // 从文件中读取CRL
    crl = PEM_read_X509_CRL(crl_file, NULL, NULL, NULL);
    fclose(crl_file);
    if (!crl) {
        printf("cannot read CRL file\n");
        return 1;
    }

    return 0;
}
